package com.web.cloud.service.pub;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.web.cloud.constances.DBConsts;
import com.web.cloud.base.dao.BaseDao;
import com.web.cloud.exception.BusinessException;
import com.web.cloud.model.pub.IBaseModel;
import com.web.cloud.utils.IdGenerator;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

/**
 * Created by liuhaiming on 15/8/12
 */
public abstract class BaseService<T extends IBaseModel> {
    @Autowired
    protected BaseDao<T> dao;

    public BaseService() {
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    public int save(T entity) throws BusinessException {
        try {
            entity.setId(IdGenerator.getInstance().nextId(this.getModuleCode()));
            entity.setDr(DBConsts.DR_NORMAL);
            this.setNewTs(entity);
            int result = this.dao.insert(entity);
            return result;
        } catch (Exception var4) {
            throw new BusinessException(var4);
        }
    }

    @Transactional( rollbackFor = {Exception.class} )
    public int save(List<T> arr) throws BusinessException {
        long ts = (new Date()).getTime();
        Iterator result = arr.iterator();

        while(result.hasNext()) {
            IBaseModel e = (IBaseModel)result.next();
            e.setId(IdGenerator.getInstance().nextId(this.getModuleCode()));
            e.setDr(DBConsts.DR_NORMAL);
            e.setTs(Long.valueOf(ts));
        }

        try {
            int result1 = this.dao.insertList(arr);
            return result1;
        } catch (Exception var6) {
            throw new BusinessException(var6);
        }
    }

    @Transactional( rollbackFor = {Exception.class} )
    public int delete(T entity) throws BusinessException {
        try {
            this.validateTs(entity);
            T newEntity = (T)entity.getClass().newInstance();
            newEntity.setId(entity.getId());
            newEntity.setDr(DBConsts.DR_DELETE);
            this.setNewTs(newEntity);
            int result = this.dao.updateByPrimaryKeySelective(newEntity);
            return result;
        } catch (Exception var5) {
            throw new BusinessException(var5);
        }
    }

    @Transactional( rollbackFor = {Exception.class} )
    public int delete(List<T> entitys) throws BusinessException {
        boolean result = false;
        int result1 = this.dao.batchDelete(entitys);
        return result1;
    }

    @Transactional( rollbackFor = {Exception.class} )
    public int delete(List<String> ids, Class<T> cls) throws BusinessException {
        ArrayList list = new ArrayList();

        try {
            Iterator e = ids.iterator();

            while(e.hasNext()) {
                String id = (String)e.next();
                IBaseModel newEntity = (IBaseModel)cls.newInstance();
                newEntity.setId(id);
                list.add(newEntity);
            }

            int result = this.delete((List)list);
            return result;
        } catch (Exception var8) {
            throw new BusinessException(var8);
        }
    }

    @Transactional(
            rollbackFor = {Exception.class}
    )
    public int update(T entity) throws BusinessException {
        try {
            this.validateTs(entity);
            this.setNewTs(entity);
            int result = this.dao.updateByPrimaryKey(entity);
            return result;
        } catch (BusinessException var4) {
            throw var4;
        } catch (Exception var5) {
            throw new BusinessException(var5);
        }
    }

    private void validateTs(T entity) throws BusinessException {
        if(entity != null && entity.getTs() != null) {
            IBaseModel origEntity = (IBaseModel)this.dao.selectByPrimaryKey(entity.getId());
            if(entity.getTs().compareTo(origEntity.getTs()) != 0) {
                throw new BusinessException("ER001");
            }
        }
    }

    protected void setNewTs(T entity) throws BusinessException {
        entity.setTs(Long.valueOf((new Date()).getTime()));
    }

    public T get(String id) {
        return (T)this.dao.selectByPrimaryKey(id);
    }

    protected T createVOInstance(T original) throws Exception {
        if(original == null) {
            original = (T)this.getGenericType().newInstance();
        }

        original.setDr(DBConsts.DR_NORMAL);
        return original;
    }

    public PageInfo<T> selectPage(int pageNum, int pageSize, String orderBy) throws Exception {
        PageHelper.startPage(pageNum, pageSize, orderBy);
        return new PageInfo(this.dao.select(this.createVOInstance((T)null)));
    }

    public PageInfo<T> selectLikePage(String searchText, int pageNum, int pageSize, String orderBy, T t) throws Exception {
        if(StringUtils.isNotEmpty(StringUtils.trim(searchText))) {
            PageHelper.startPage(pageNum, pageSize, orderBy);
            return new PageInfo(this.dao.selectLike(searchText, this.createVOInstance(t)));
        } else {
            return this.selectPage(pageNum, pageSize, orderBy, this.createVOInstance(t));
        }
    }

    public PageInfo<T> selectPage(int pageNum, int pageSize, String orderBy, T t) throws Exception {
        PageHelper.startPage(pageNum, pageSize, orderBy);
        t.setDr(DBConsts.DR_NORMAL);
        return new PageInfo(this.dao.select(t));
    }

    public List<T> selectAll() throws Exception {
        T t = (T)this.getGenericType().newInstance();
        t.setDr(DBConsts.DR_NORMAL);
        return this.dao.select(t);
    }

    public List<T> get(List<String> ids) {
        return this.dao.selectByIdList(ids);
    }

    protected Class<T> getGenericType() throws BusinessException {
        Class cls = this.getGenericType(this.dao.getClass());
        if(cls == null) {
            throw new BusinessException("无法获取Mapper<T>泛型类型:" + this.dao.getClass().getName());
        } else {
            return cls;
        }
    }

    private Class<T> getGenericType(Class cls) {
        Type[] types = cls.getGenericInterfaces();
        Type[] var3 = types;
        int var4 = types.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            Type type = var3[var5];
            if(type instanceof ParameterizedType) {
                ParameterizedType t = (ParameterizedType)type;
                return (Class)t.getActualTypeArguments()[0];
            }

            if(type instanceof Class) {
                return this.getGenericType((Class)type);
            }
        }

        return null;
    }

    public String getModuleCode() {
        return "SM";
    }

    public int updateStatus(T entity, short status) throws BusinessException {
        try {
            this.validateTs(entity);
            T newEntity = (T)entity.getClass().newInstance();
            newEntity.setId(entity.getId());
            PropertyUtils.setSimpleProperty(newEntity, DBConsts.FIELD_STATUS, Short.valueOf(status));
            this.setNewTs(newEntity);
            int result = this.dao.updateByPrimaryKeySelective(newEntity);
            return result;
        } catch (Exception var6) {
            throw new BusinessException(var6);
        }
    }

    public int enable(T entity) throws BusinessException {
        return this.updateStatus(entity, DBConsts.STATUS_ENABLE.shortValue());
    }

    public int enable(List<T> entitys) throws BusinessException {
        int result = 0;

        T entity;
        for(Iterator var3 = entitys.iterator(); var3.hasNext(); result += this.enable(entity)) {
            entity = (T)var3.next();
        }

        return result;
    }

    public int disable(T entity) throws BusinessException {
        return this.updateStatus(entity, DBConsts.STATUS_DISABLE.shortValue());
    }

    public int disable(List<T> entitys) throws BusinessException {
        int result = 0;

        T entity;
        for(Iterator var3 = entitys.iterator(); var3.hasNext(); result += this.disable(entity)) {
            entity = (T)var3.next();
        }

        return result;
    }

    public List<T> select(List<String> idList) {
        return (List)(idList != null && !idList.isEmpty()?this.dao.selectByIdList(idList):new ArrayList());
    }
}
